package org.gaming.prefab.thing;


import java.util.List;

import org.gaming.common.asserts.ITipCause;
import org.gaming.prefab.IGameCause;
import org.gaming.prefab.exception.ThingLackException;
import org.gaming.prefab.thing.cost.CostReceipt;
import org.gaming.prefab.thing.cost.ICostThing;
import org.gaming.prefab.thing.reward.IRewardThing;
import org.gaming.prefab.thing.reward.RewardReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 物品处理
 */
public abstract class ThingStorer<Num extends Number, Reward extends IRewardThing<Num>, Cost extends ICostThing<Num>, RReceipt extends RewardReceipt<Num>, CReceipt extends CostReceipt<Num>> {
	
	protected Logger logger = LoggerFactory.getLogger(ThingStorer.class);
	
    /**
     * 资源类型
     */
	protected abstract IThingType thingType();
    /**
     * 物品不足编码
     */
	protected abstract ITipCause lackCode();
    /**
     * 获取拥有的数量
     */
	public abstract Num getCount(long entityId, int thingId);
	/**
	 * 尝试添加
	 * @param entityId
	 * @param rewardThings
	 * @return
	 */
	protected boolean tryAdd(long entityId, List<Reward> rewardThings) {
		return true;
	}
    /**
     * 添加之前
     */
	protected final void prepareAdd(long entityId, List<Reward> rewardThings) {
    	for(Reward thing : rewardThings) {
    		requireRewardPositive(thing);
		}
    }
	
	protected final RReceipt add(long entityId, int dbZone, List<Reward> rewardThings, IGameCause cause, String remark) {
		RReceipt receipt = this.doAdd(entityId, rewardThings, cause, remark);
		this.afterAdd(entityId, dbZone, receipt, cause, remark);
		return receipt;
	}
	
    /**
     * 执行添加
     * @param rid
     * @param rewardSet
     * @param gameEvent
     * @return
     */
    protected abstract RReceipt doAdd(long entityId, List<Reward> rewardThings, IGameCause cause, String remark);
    /**
     * 执行添加后
     * @param entityId
     * @param receipt
     */
    protected void afterAdd(long entityId, int dbZone, RReceipt receipt, IGameCause cause, String remark) {}
    /**
     * 物品是否足够
     * @param rid
     * @param thing
     * @return
     */
    protected abstract boolean isEnough(long entityId, Cost thing);
//    {
//    	requirePositive(thing);
//        long remainCount = getCount(entityId, thing.getThingId()) - thing.getNum();
//        return remainCount >= 0;
//    }
    /**
     * 消耗之前
     * @param rid
     * @param costSet
     * @param gameEvent
     * @return
     */
    protected final void prepareCost(long entityId, List<Cost> costThings, IGameCause cause) {
    	for(Cost thing : costThings) {
    		if(!isEnough(entityId, thing)) {
    			throw new ThingLackException(cause, lackCode());
    		}
    	}
    }
    
    protected final CReceipt cost(long entityId, int dbZone, List<Cost> costThings, IGameCause cause, String remark) {
    	CReceipt receipt = doCost(entityId, costThings, cause, remark);
    	afterCost(entityId, dbZone, receipt, cause, remark);
    	return receipt;
    }
    
    /**
     * 执行消耗
     * @param rid
     * @param costSet
     * @param gameEvent
     */
    protected abstract CReceipt doCost(long entityId, List<Cost> costThings, IGameCause cause, String remark);
    /**
     * 消耗后执行的处理
     * @param entityId
     * @param costReceipt
     * @param cause
     * @param remark
     */
    protected void afterCost(long entityId, int dbZone, CReceipt receipt, IGameCause cause, String remark) {}
    /**
     * 验证非负数
     * @param value
     * @param thingType
     */
    protected abstract void requireCostPositive(Cost cost);
    
    protected abstract void requireRewardPositive(Reward reward);
//    {
//    	if(thing.getNum() <= 0) {
//    		throw new RuntimeException("物品数量必须大于0，实际：" + thing.getNum());
//    	}
//    }
    
    /**
     * 获取持有者的名字
     * @param entityId
     * @return
     */
    protected abstract String getOwnerName(long entityId);
}
